<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="bootstrap.css" />
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.js"></script>
    <script src="bootstrap.js"></script>
    <script src="axios.js"></script>
  </head>
  <body>
    <!-- 下拉列表 -->
    <h3>选择城市</h3>
    <div class="form-group" style="display: flex">
      <select class="form-control" id="provinceSelect">
        <option>湖北省</option>
      </select>
      <select class="form-control" id="citySelect">
        <option>武汉市</option>
      </select>
      <select class="form-control" id="areaSelect">
        <option>青山区</option>
      </select>
    </div>
    <!-- xx地区的显示 -->
    <h3>
      <strong id="provinceData" style="color: rgb(26, 127, 190)">湖北省</strong>
      <strong id="cityData" style="color: rgb(26, 127, 190)">武汉市</strong>
      <strong id="areaData" style="color: rgb(26, 127, 190)">青山区</strong>
      <span>未来七日天气预报</span>
    </h3>
    <!-- 天气表格 -->
    <table class="table table-striped table-bordered">
      <thead>
        <tr class="info">
          <th>日期</th>
          <th>白天天气</th>
          <th>白天风向</th>
          <th>白天风力</th>
          <th>夜晚天气</th>
          <th>夜晚风向</th>
          <th>夜晚风力</th>
          <th>最高温度</th>
          <th>最低温度</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td colspan="9" style="text-align: center">暂无数据</td>
        </tr>
      </tbody>
    </table>

    <!-- 简答题 -->
    <script>
      /* 一、简答题
      1、es6新增的新特性有哪些？（不低于8个）【5分】
      1.let、const
      2.箭头函数
      3.类
      4.字符串模块
      5.symbols
      6.Promises
      7.解构赋值
      8.展开运算符

      2、详细解释一下事件循环event loop？【5分】
      js是单线程语言，s执行时，遇到同步任务，就将同步任务按照执行顺序排列到执行栈中。遇到异步任务，就会放入事件队列
      主线程执行完执行栈中的同步任务，再依次取出事件队列中的任务执行，这个循环的过程是事件循环。
      3、从浏览器地址栏输入url到页面最终呈现完整中间经历了什么？【5分】
      当浏览器的网络线程收到 HTML 文档后，会产生一个渲染任务，并将其传递给渲染主线。
      （1）html的解析
      解析使启动预解析的线程，提前下载css和js的外部文件，解析到link部分时，不会停止css的解析，因为css的下载和解析是在预解析的线程中，解析到script部分时候，
      html会停止解析，转而解析js，修改当前的DOM树，所以DOM树的生成必须暂停。这就是js会阻塞html解析的根本原因。
      （2）样式计算
      html解析后会得到DOM树和css树，主线程会遍历得到的DOM树，依次为树中的每个节点计算出它最终的样式
      （3）布局
      布局阶段会依次遍历 DOM 树的每一个节点，计算每个节点的几何信息，DOM 树和布局树并非一一对应
      （4）分层
      主线程会使用一套复杂的策略对整个布局树中进行分层。
      分层的好处在于，将来某一个层改变后，仅会对该层进行后续处理
      （5）绘制
      每个层单独产生绘制指令集
      （6）分块
      合成线程首先对每个图层进行分块，将其划分为更多的小区域
      （7）光栅化
      GPU 进程会开启多个线程来完成光栅化，并且优先处理靠近视口区域的块。
      （8）成像

      4、http和https的概念和区别？【5分】
      http :超文本传输协议
      https ：比http更安全

      5、前端性能优化的手段？【5分】
      1.减少请求数量
      2.减少资源大小
      3.优化资源加载
      4.减少重绘回流
      5.性能更好的API

      6、深浅拷贝的区别和实现方式有哪些？【5分】
      浅拷贝只拷贝属性基本数据类型的值, 如果对象中的属性值存在引用数据类型时, 只拷贝引用地址
      深拷贝：递归拷贝，JOSN.parse()
      浅拷贝：展开运算符，Object.assign，for in

      7、说一下垃圾回收机制？【5分】
      垃圾回收机制就是指，当声明一个变量时，会分配一块内存空间，当不再使用使，内存就会被清除，
      有一些情况，如闭包或未被清除的定时器会造成内存泄漏。

      8、this指向有哪几种？如何改变【5分】
      this 总是指向函数的直接调用者
      构造函数时，this 指向 new 出来的实例
      在事件中， this 指向触发这个事件的对象
      改变：call() apply()俩方法调用函数并改变this，bind() 改变this不调用方法

    */
    </script>

    <!-- 代码题 -->
    <script>
      var tbody = document.querySelector("tbody");

      // 渲染下拉数据的函数
      function renderOption(data, select) {
        data.forEach((item) => {
          var option = document.createElement("option");
          option.text = item.name;
          option.value = item.name;
          select.add(option);
        });
      }

      // 获取地区数据
      // 为空查询所有省份，传入省份查询市，传入市查询区
      async function fetchDistrictData(keywords) {
        const response = await axios.get(
          "https://restapi.amap.com/v3/config/district",
          {
            params: {
              keywords,
              key: "a321f609de73d8e07ba4505d0d8e00a3",
            },
          }
        );
        // 可选链
        return response.data?.districts?.[0]?.districts || [];
      }

      // 渲染省列表
      async function fetchProvinceData() {
        const provinceData = await fetchDistrictData("");
        renderOption(provinceData, provinceSelect);
      }
      fetchProvinceData();

      // 渲染市列表
      provinceSelect.addEventListener("change", async function () {
        citySelect.length = 0;
        const cityData = await fetchDistrictData(provinceSelect.value);
        renderOption(cityData, citySelect);
        tbody.innerHTML = `<tr><td colspan="9" style="text-align: center">暂无数据</td></tr>`;
      });

      // 渲染区列表
      citySelect.addEventListener("change", async function () {
        areaSelect.length = 0;
        const areaData = await fetchDistrictData(citySelect.value);
        renderOption(areaData, areaSelect);
      });

      // 区域改变请求天气
      areaSelect.addEventListener("change", function () {
        getWeather(provinceSelect.value, citySelect.value, areaSelect.value);
        // 标题地区文本
        provinceData.innerHTML = provinceSelect.value;
        cityData.innerHTML = citySelect.value;
        areaData.innerHTML = areaSelect.value;
      });

      // 获取天气(传入省市区当参数发请求)
      async function getWeather(province, city, county) {
        const response = await axios.get("http://localhost:3000/api/weather", {
          params: { province, city, county },
        });
        var data = response.data.data.forecast_24h;
        // 数组数组转对象数组
        const dataArray = Object.values(data);
        renderTable(dataArray);
      }

      // 渲染表格结构
      function renderTable(data) {
        var mapData = data.map((item) => {
          return `<tr>
            <td>${item.time}</td>
            <td>${item.day_weather}</td>
            <td>${item.day_wind_direction}</td>
            <td>${item.day_wind_power}</td>
            <td>${item.night_weather}</td>
            <td>${item.night_wind_direction}</td>
            <td>${item.night_wind_power}</td>
            <td>${item.max_degree}</td>
            <td>${item.min_degree}</td>
          </tr>`;
        });
        tbody.innerHTML = mapData.join("");
      }

      // 默认渲染
      getWeather("湖北省", "武汉市", "青山区");
    </script>
  </body>
</html>
